package ar.uba.dc.tl.mylanga.semantic;

import ar.uba.dc.tl.mylanga.analysis.AnalysisAdapter;
import ar.uba.dc.tl.mylanga.node.*;

public abstract class SemanticRule extends AnalysisAdapter {

	private String name;
	private PProgram program;

	public SemanticRule(String name, PProgram program) {
		this.setName(name);
		this.setProgram(program);
	}

	public abstract void check();

	public String getName() {
		return this.name;
	}

	public PProgram getProgram() {
		return this.program;
	}

	public void setName(String name) {
		assert name != null;

		this.name = name;
	}

	public void setProgram(PProgram program) {
		assert program != null;

		this.program = program;
	}

    @Override
    public void caseAProgram(AProgram node) {
        for (PFunctionDefinition functionDefinition : node.getFunctionDefinitions()) {
            functionDefinition.apply(this);
        }

        node.getCommand().apply(this);
    }

    @Override
    public void caseAPlotCommand(APlotCommand node) {
        node.getFirst().apply(this);
        node.getSecond().apply(this);
    }

    @Override
    public void caseAFunctionDefinition(AFunctionDefinition node) {
        for (PParameter parameter : node.getParameters()) {
            parameter.apply(this);
        }
        node.getBody().apply(this);
    }

    @Override
    public void caseAParameter(AParameter node) {
    }

    @Override
    public void caseAAssignmentStatement(AAssignmentStatement node) {
        node.getRightValue().apply(this);
    }

    @Override
    public void caseACompoundStatement(ACompoundStatement node) {
        for (PStatement statement : node.getStatements()) {
            statement.apply(this);
        }
    }

    @Override
    public void caseAIfThenStatement(AIfThenStatement node) {
        node.getCondition().apply(this);
        node.getThenStatements().apply(this);
    }

    @Override
    public void caseAIfThenElseStatement(AIfThenElseStatement node) {
        node.getCondition().apply(this);
        node.getThenStatements().apply(this);
        node.getElseStatements().apply(this);
    }

    @Override
    public void caseAReturnStatement(AReturnStatement node) {
        node.getNumericExpression().apply(this);
    }

    @Override
    public void caseAWhileStatement(AWhileStatement node) {
        node.getCondition().apply(this);
        node.getBody().apply(this);
    }

    @Override
    public void caseABooleanExpression(ABooleanExpression node) {
        node.getBooleanExpression().apply(this);
    }

    @Override
    public void caseANumericExpression(ANumericExpression node) {
        node.getNumericExpression().apply(this);
    }

    @Override
    public void caseANegationBooleanExpression(ANegationBooleanExpression node) {
        node.getBooleanExpression().apply(this);
    }

    @Override
    public void caseARelationalBooleanExpression(ARelationalBooleanExpression node) {
        node.getRelationalExpression().apply(this);
    }

    @Override
    public void caseAOrBooleanExpression(AOrBooleanExpression node) {
        node.getLeft().apply(this);
        node.getRight().apply(this);
    }

    @Override
    public void caseAAndBooleanExpression(AAndBooleanExpression node) {
        node.getLeft().apply(this);
        node.getRight().apply(this);
    }

    @Override
    public void caseAVariableNumericExpression(AVariableNumericExpression node) {

    }

    @Override
    public void caseAFunctionCallNumericExpression(AFunctionCallNumericExpression node) {
        node.getFunctionCall().apply(this);
    }

    @Override
    public void caseAUnaryMinusNumericExpression(AUnaryMinusNumericExpression node) {
        node.getNumericExpression().apply(this);
    }

    @Override
    public void caseAAdditionNumericExpression(AAdditionNumericExpression node) {
        node.getLeft().apply(this);
        node.getRight().apply(this);
    }

    @Override
    public void caseASubtractionNumericExpression(ASubtractionNumericExpression node) {
        node.getLeft().apply(this);
        node.getRight().apply(this);
    }

    @Override
    public void caseAMultiplicationNumericExpression(AMultiplicationNumericExpression node) {
        node.getLeft().apply(this);
        node.getRight().apply(this);
    }

    @Override
    public void caseADivisionNumericExpression(ADivisionNumericExpression node) {
        node.getLeft().apply(this);
        node.getRight().apply(this);
    }

    @Override
    public void caseAExponentiationNumericExpression(AExponentiationNumericExpression node) {
        node.getBase().apply(this);
        node.getExponent().apply(this);
    }

    @Override
    public void caseAFunctionCall(AFunctionCall node) {
        for (PNumericExpression parameter : node.getParameters()) {
            parameter.apply(this);
        }
    }

    @Override
    public void caseAEqualRelationalExpression(AEqualRelationalExpression node) {
        node.getLeft().apply(this);
        node.getRight().apply(this);
    }

    @Override
    public void caseANotEqualRelationalExpression(ANotEqualRelationalExpression node) {
        node.getLeft().apply(this);
        node.getRight().apply(this);
    }

    @Override
    public void caseAGreaterThanRelationalExpression(AGreaterThanRelationalExpression node) {
        node.getLeft().apply(this);
        node.getRight().apply(this);
    }

    @Override
    public void caseAGreaterThanOrEqualRelationalExpression(AGreaterThanOrEqualRelationalExpression node) {
        node.getLeft().apply(this);
        node.getRight().apply(this);
    }

    @Override
    public void caseALessThanRelationalExpression(ALessThanRelationalExpression node) {
        node.getLeft().apply(this);
        node.getRight().apply(this);
    }

    @Override
    public void caseALessThanOrEqualRelationalExpression(ALessThanOrEqualRelationalExpression node) {
        node.getLeft().apply(this);
        node.getRight().apply(this);
    }
}
